package com.wm.wmim.server.service.impl;

import com.wm.wmim.common.bo.resp.CommonBizRespBo;
import com.wm.wmim.common.enums.CommonBizCodeEnum;
import com.wm.wmim.server.dbservice.ChatListDbService;
import com.wm.wmim.server.dbservice.ChatMessageRecordDbService;
import com.wm.wmim.server.dbservice.UserInfoDbService;
import com.wm.wmim.server.dto.bo.WsMessageBO;
import com.wm.wmim.server.dto.bo.req.PrivateChatOnMessageReqBodyBO;
import com.wm.wmim.server.dto.bo.resp.PrivateChatOnMessageRespBodyBO;
import com.wm.wmim.server.dto.vo.resp.ChatMessageRecordVO;
import com.wm.wmim.server.entity.ChatListDO;
import com.wm.wmim.server.entity.ChatMessageRecordDO;
import com.wm.wmim.server.entity.UserInfoDO;
import com.wm.wmim.server.enums.WsMessageTypeEnum;
import com.wm.wmim.server.rpcinvoke.PushWsMessageRpcInvokeService;
import com.wm.wmim.server.service.AckService;
import com.wm.wmim.server.service.ChatService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;

/**
 * @author weiming
 * @date 2024/8/27 21:36
 * @description
 */
@Service
public class ChatServiceImpl implements ChatService {

    @Resource
    private UserInfoDbService userInfoDbService;
    @Resource
    private ChatMessageRecordDbService chatMessageRecordDbService;
    @Resource
    private PushWsMessageRpcInvokeService pushWsMessageRpcInvokeService;
    @Resource
    private ChatListDbService chatListDbService;
    @Resource
    private AckService ackService;


    @Override
    public CommonBizRespBo<PrivateChatOnMessageRespBodyBO> sendPrivateMessage(PrivateChatOnMessageReqBodyBO reqBO) {
        Long fromUserId = reqBO.getFromUserId();
        Long toUserId = reqBO.getToUserId();
        List<UserInfoDO> userInfoDOS = userInfoDbService.listByIds(Arrays.asList(fromUserId, toUserId));
        if (CollectionUtils.isEmpty(userInfoDOS)){
            return CommonBizRespBo.buildErrorResp(CommonBizCodeEnum.PARAM_ERROR);
        }
        // 查询接收方消息列表有没有, 没有的话, 创建一个, 有的话更新
        ChatListDO toChatListDO = chatListDbService.getByUserIdAndFriendID(reqBO.getToUserId(), reqBO.getFromUserId());
        if (toChatListDO == null) {
            toChatListDO = new ChatListDO();
            toChatListDO.setUserId(reqBO.getToUserId());
            toChatListDO.setFriendId(reqBO.getFromUserId());
        }
        toChatListDO.setLastMessageContent(reqBO.getMessageContent());
        toChatListDO.setLastMessageTime(reqBO.getSendTime());
        toChatListDO.setUnreadMessageCount(toChatListDO.getUnreadMessageCount() == null ? 1 : toChatListDO.getUnreadMessageCount() + 1);

        // 查询发送方消息列表有没有, 没有的话, 创建一个, 有的话更新
        ChatListDO fromChatListDO = chatListDbService.getByUserIdAndFriendID(reqBO.getFromUserId(), reqBO.getToUserId());
        if (fromChatListDO == null) {
            fromChatListDO = new ChatListDO();
            fromChatListDO.setUserId(reqBO.getFromUserId());
            fromChatListDO.setFriendId(reqBO.getToUserId());
        }
        fromChatListDO.setLastMessageContent(reqBO.getMessageContent());
        fromChatListDO.setLastMessageTime(reqBO.getSendTime());

        // 保存记录
        ChatMessageRecordDO recipientsMessage = this.buildRecipientsMessage(reqBO);
        ChatMessageRecordDO senderMessage = this.buildSenderMessage(reqBO);

        // TODO 事务
        chatListDbService.saveOrUpdate(toChatListDO);
        chatListDbService.saveOrUpdate(fromChatListDO);
        chatMessageRecordDbService.saveBatch(Arrays.asList(senderMessage, recipientsMessage));

        // 推送消息
        this.pushMessage(recipientsMessage, toUserId);

        // 返回ACK
        PrivateChatOnMessageRespBodyBO privateChatOnMessageRespBodyBO = new PrivateChatOnMessageRespBodyBO();
        privateChatOnMessageRespBodyBO.setResult(true);
        privateChatOnMessageRespBodyBO.setId(senderMessage.getId());
        privateChatOnMessageRespBodyBO.setClientMessageId(senderMessage.getClientMessageId());
        privateChatOnMessageRespBodyBO.setFriendId(senderMessage.getFriendId());

        return CommonBizRespBo.buildSuccessResp(privateChatOnMessageRespBodyBO);
    }

    private void pushMessage(ChatMessageRecordDO reqBO, Long toUserId) {
        CompletableFuture.runAsync(() -> {
            // TODO 异步推送
            ChatMessageRecordVO chatMessageRecordVO = new ChatMessageRecordVO();
            chatMessageRecordVO.setId(reqBO.getId());
            chatMessageRecordVO.setClientMessageId(reqBO.getClientMessageId());
            chatMessageRecordVO.setUserId(reqBO.getUserId());
            chatMessageRecordVO.setFriendId(reqBO.getFriendId());
            chatMessageRecordVO.setDirection(1);
            chatMessageRecordVO.setMessageContent(reqBO.getMessageContent());
            chatMessageRecordVO.setMessageContentType(reqBO.getMessageContentType());
            chatMessageRecordVO.setSendTime(reqBO.getSendTime());

            WsMessageBO<ChatMessageRecordVO> wsMessageBO = new WsMessageBO<>();
            wsMessageBO.setMessageType(WsMessageTypeEnum.PRIVATE_CHAT.getCode());
            wsMessageBO.setMessageBody(chatMessageRecordVO);
            Boolean push = pushWsMessageRpcInvokeService.push(toUserId, wsMessageBO);
            // TODO 等待客户端ACK

        });
    }

    private ChatMessageRecordDO buildSenderMessage(PrivateChatOnMessageReqBodyBO reqBO) {
        ChatMessageRecordDO recordDO = new ChatMessageRecordDO();
        recordDO.setClientMessageId(reqBO.getClientMessageId());
        recordDO.setUserId(reqBO.getFromUserId());
        recordDO.setFriendId(reqBO.getToUserId());
        recordDO.setDirection(0);
        recordDO.setMessageContent(reqBO.getMessageContent());
        recordDO.setMessageContentType(reqBO.getMessageContentType());
        recordDO.setSendTime(reqBO.getSendTime());
        recordDO.setClientAck(0);
        return recordDO;
    }

    private ChatMessageRecordDO buildRecipientsMessage(PrivateChatOnMessageReqBodyBO reqBO) {
        ChatMessageRecordDO recordDO = new ChatMessageRecordDO();
        recordDO.setClientMessageId(reqBO.getClientMessageId());
        recordDO.setUserId(reqBO.getToUserId());
        recordDO.setFriendId(reqBO.getFromUserId());
        recordDO.setDirection(1);
        recordDO.setMessageContent(reqBO.getMessageContent());
        recordDO.setMessageContentType(reqBO.getMessageContentType());
        recordDO.setSendTime(reqBO.getSendTime());
        recordDO.setClientAck(0);
        return recordDO;

    }

}
